package com.minivision.fdiot.rest;

import java.util.List;
import java.util.concurrent.ExecutorService;

import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.minivision.fdiot.common.PageResult;
import com.minivision.fdiot.common.RestResult;
import com.minivision.fdiot.entity.MqttLog;
import com.minivision.fdiot.exception.ServiceException;
import com.minivision.fdiot.mqtt.handler.CommonSender;
import com.minivision.fdiot.rest.param.MqttLogParam;
import com.minivision.fdiot.rest.param.QueryMqttLogParam;
import com.minivision.fdiot.service.MqttLogService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping(value = "mqttlog", method = RequestMethod.POST)
@Api(tags = "MqttLogApi", value = "IoT Platform MqttLog Apis")
@Slf4j
public class MqttLogApi {
  
  @Autowired
  private MqttLogService mqttLogService;
  
  @Autowired
  private CommonSender sender;
  
  @Autowired
  @Qualifier("mqttSenderWorker")
  private ExecutorService mqttSenderWorker;
  
  @RequestMapping("repush/{id}")
  @ApiOperation(value = "重发推送失败消息", notes = "重发推送失败消息")
  public RestResult<Boolean> repush(@PathVariable Long id) {
    RestResult<Boolean> response = new RestResult<>(true);
    MqttLog log = mqttLogService.find(id);
    if (log != null) {
      response.setData(sender.repush(log));
      mqttLogService.delete(id);
    }
    return response;
  }
  
  @RequestMapping("repush/{deviceSn}")
  @ApiOperation(value = "重发推送失败消息", notes = "重发推送失败消息")
  public RestResult<String> repush(@PathVariable String deviceSn) {
    List<MqttLog> logs = mqttLogService.findByDeviceSn(deviceSn);
    if (!CollectionUtils.isEmpty(logs)) {
      mqttSenderWorker.execute(() -> {
        logs.stream().forEach((log) -> {
          try {
            sender.repush(log);
            mqttLogService.delete(log.getId());
          } catch (Exception e) {
            MqttLogApi.log.error("repush failed, log:" + log, e);
          }
        });
      });
    }
    return new RestResult<>("");
  }
  
  @RequestMapping("listbydate")
  @ApiOperation(value = "按时间查询MQTT推送失败日志", notes = "按时间查询MQTT推送失败日志")
  public RestResult<PageResult<MqttLog>> findMqttLogsByDate(@Valid @ModelAttribute MqttLogParam param, BindingResult errResult) {
    if (errResult.hasErrors()) {
      List<ObjectError> errorList = errResult.getAllErrors();
      for(ObjectError error : errorList){
        log.error(error.getDefaultMessage());
      }
      throw new ServiceException(errorList.get(0).getDefaultMessage());
    }
    
    if (StringUtils.isBlank(param.getStartTime())) {
      param.setStartTime("1900-01-01 00:00:00");
    } else {
      param.setStartTime(param.getStartTime() + " 00:00:00");
    }
    if (StringUtils.isBlank(param.getEndTime())) {
      param.setEndTime("2999-12-31 23:59:59");
    } else {
      param.setEndTime(param.getEndTime() + " 23:59:59");
    }
    
    PageResult<MqttLog> result = new PageResult<>();
    try {
      Page<MqttLog> pageResult = mqttLogService.findByCreateTimeBetween(param);
      if (pageResult != null && pageResult.hasContent()) {
        result.setPages(pageResult.getTotalPages());
        result.setTotal(pageResult.getTotalElements());
        result.setRows(pageResult.getContent());
      }
    } catch (Exception e) {
      log.error("find mqttlog list by date failed", e);
      throw new ServiceException("按时间查询MQTT推送失败日志异常");
    }

    return new RestResult<>(result);
  }
  
  @RequestMapping("list")
  @ApiOperation(value = "查询MQTT推送失败日志", notes = "查询MQTT推送失败日志")
  public RestResult<PageResult<MqttLog>> findMqttLogs(@Valid @ModelAttribute QueryMqttLogParam param, BindingResult errResult) {
    if (errResult.hasErrors()) {
      List<ObjectError> errorList = errResult.getAllErrors();
      for(ObjectError error : errorList){
        log.error(error.getDefaultMessage());
      }
      throw new ServiceException(errorList.get(0).getDefaultMessage());
    }
    
    PageResult<MqttLog> result = new PageResult<>();
    try {
      Page<MqttLog> pageResult = mqttLogService.findByPage(param);
      if (pageResult != null && pageResult.hasContent()) {
        result.setPages(pageResult.getTotalPages());
        result.setTotal(pageResult.getTotalElements());
        result.setRows(pageResult.getContent());
      }
    } catch (Exception e) {
      log.error("find mqttlog list failed", e);
      throw new ServiceException("查询MQTT推送失败日志异常");
    }

    return new RestResult<>(result);
  }

}
